using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using Phydeaux.Utilities;

namespace BTreeSharp
{
    /// <summary>
    /// Implements a B-Tree containing tuple of type RecordType
    /// Each RecordType public properties are phisically stored in the tree 
    /// </summary>
    /// <typeparam name="RecordType">The tuple type to store in the tree</typeparam>
    /// <typeparam name="KeyType">The type used by key</typeparam>
    public class BTree<RecordType, KeyType> where KeyType : IComparable
    {
        private IByteConverter byteConverter;

        protected IByteConverter ByteConverter
        {
            get { return byteConverter; }
            set { byteConverter = value; }
        }
	
        private BTree() {
            
        }
        private Surface surface;
        private long initialRecordCount;
        private int order;
        private long recordLen;
        private IAccessor accessor;
        private BTree<RecordType, KeyType> BuildUp()
        {
            
            accessor = BuildUpAccessor();
            int tmpLen = 0;
            foreach (Type t in accessor.Types)
            {
                if (!byteConverter.CanConvert(t, out tmpLen))
                    throw new Exception(string.Format("Can't build up a tree for type {0} due to unhandled property type {1}", typeof(RecordType).ToString(), t.ToString()));
                else
                    recordLen += tmpLen;
            }
            return this;
        }

        private IAccessor BuildUpAccessor()
        {
            List<PropertyInfo> props = new List<PropertyInfo>();
            props.AddRange(typeof(RecordType).GetProperties(BindingFlags.Public|BindingFlags.Instance));
            return BuiltInAccessor<RecordType>.Create(props);
        }
        /// <summary>
        /// Creates a new B-Tree instance
        /// </summary>
        /// <param name="surface">The virtual support in wich objects are stored</param>
        /// <param name="order">The b-tree order: each node ( excluded the root ) contains at least order/2 keys and at most order keys</param>
        /// <param name="initialRecordCount">The initial storage allocated, computed in number of record</param>
        /// <param name="keyProperty">The property on the record to use as a key</param>
        /// <returns>A new btree instance</returns>
        public static BTree<RecordType, KeyType> Create(Surface surface
                                    ,int order
                                    ,long initialRecordCount
                                    ,string keyProperty
                                    )
        {
            return BTree<RecordType, KeyType>.Create(
                                                    surface
                                                    , order
                                                    , initialRecordCount
                                                    , keyProperty
                                                    , new BuiltInByteConverter());
        }
        /// <summary>
        /// Creates a new B-Tree instance
        /// </summary>
        /// <param name="surface">The virtual support in wich objects are stored</param>
        /// <param name="order">The b-tree order: each node ( excluded the root ) contains at least order/2 keys and at most order keys</param>
        /// <param name="initialRecordCount">The initial storage allocated, computed in number of record</param>
        /// <param name="keyProperty">The property on the record to use as a key: Null if the record itself act as a key ( ie it is IComparable)</param>
        /// <param name="byteConverter">An object able to convert other objects in a byte stream representation</param>
        /// <returns></returns>
        public static BTree<RecordType, KeyType> Create(Surface surface
                                   , int order
                                   , long initialRecordCount
                                   , string keyProperty
                                   ,IByteConverter byteConverter
                                   )
        {
            BTree<RecordType, KeyType> tree = new BTree<RecordType, KeyType>();
            tree.ByteConverter = byteConverter;
            tree.surface = surface;
            tree.initialRecordCount = initialRecordCount;
            tree.order = order;
            return tree.BuildUp();
        }
        /// <summary>
        /// Insert a record in the BTRee
        /// </summary>
        /// <param name="record">The record instance</param>
        /// <returns>The current BTree instance</returns>
        public BTree<RecordType,KeyType> Insert(RecordType record)
        {
            throw new NotImplementedException();
            return this;
        }
        /// <summary>
        /// Get an instance of an object searching by key
        /// </summary>
        /// <param name="key">The key to search for</param>
        /// <returns>The instance of the stored object. Throw if the object is not in the tree</returns>
        public RecordType Get(KeyType key)
        {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Get a list of objects contained in a key range
        /// </summary>
        /// <param name="keyFirst">the lower bound of the value key to search for</param>
        /// <param name="keyLast">the upper bound of the value key to search for</param>
        /// <returns>a collection of objects satisfying the criteria</returns>
        public IList<RecordType> Get(KeyType keyFirst, KeyType keyLast)
        {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Get an instance of an object searching by key
        /// </summary>
        /// <param name="key">The key to search for</param>
        /// <param name="throwIfNotFound">true if an exception must be trown if no object found,false to return null if no object found</param>
        /// <returns>The object found or null</returns>
        public RecordType Get(KeyType key,bool throwIfNotFound)
        {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Delete an object instance based on its key
        /// </summary>
        /// <param name="key">The key to identify the object to delete</param>
        /// <returns></returns>
        public BTree<RecordType, KeyType> Delete(KeyType key)
        {
            throw new NotImplementedException();
            return this;
        }
        /// <summary>
        /// Replace an object instance contained in the B-Tree based on the key
        /// </summary>
        /// <param name="record">the object to replace</param>
        /// <returns>The current btree instance</returns>
        public BTree<RecordType, KeyType> Replace(RecordType record)
        {
            throw new NotImplementedException();
            return this;
        }


    }
}
